/* Copyright © Worklight Ltd. 2006-2011.  All rights reserved. */

package com.worklight.androidgap;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;

import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.Log;

public class WLAndroidUtils {

	public static final String LOG_CAT = "WLDroidGap";
	public static final int ANDROID_BUFFER_8K = 8192;
	// SharedPreference name constant
	public static final String WL_PREFS = "WLPrefs";

	public static Drawable findDrawableAsset(WLDroidGap wlDroidGap, String path) {
		Drawable d = null;
		InputStream in = null;
		String absolutePath = wlDroidGap.getLocalStorageWebRoot() + "/" + path;		
		
		try {
			in = new FileInputStream(new File(absolutePath));					
			d = Drawable.createFromStream(in, path);
		} catch (IOException e) {
			error("Failed to load icon from path " + path);
		} finally {
			try {
				if (in != null){
					in.close();					
				}
			} catch (IOException e) {
				error("Error closing icon stream for " + absolutePath, e);
			}
		}
		return d;
	}
	
	public static Drawable scaleImage(Drawable drawable, float scaleWidth, float scaleHeight) {
		Drawable resizedDrawable = null;
		if (drawable != null) {
		    Bitmap bitmapOrg = ((BitmapDrawable) drawable).getBitmap();
		    int width = bitmapOrg.getWidth();
		    int height = bitmapOrg.getHeight();
		    // create a matrix for the manipulation
		    Matrix matrix = new Matrix();
		    // resize the bit map
		    matrix.postScale(scaleWidth, scaleHeight);
		    Bitmap resizedBitmap = Bitmap.createBitmap(bitmapOrg, 0, 0, width, height, matrix, true);
		    // make a Drawable from Bitmap to allow to set the BitMap
		    resizedDrawable = new BitmapDrawable(resizedBitmap);
		}
		return resizedDrawable;
	}

	public static int getResourceId(Context context, String resourceCategory, String resourceName) throws NoSuchResourceException {
		int resourceId = -1;
		try {
			@SuppressWarnings("rawtypes")
			Class[] classes = Class.forName(context.getPackageName() + ".R").getDeclaredClasses();
			for (int i = 0; i < classes.length; i++) {
				if (classes[i].getSimpleName().equals(resourceCategory)){
					resourceId = classes[i].getField(resourceName).getInt(null);
					break;
				}
			}
		} catch (Exception e) {
			throw new NoSuchResourceException("Failed to find resource R." + resourceCategory + "." + resourceName, e);
		}
		return resourceId;
	}
	
	/**
	 * copy source file to destination file.
	 * If the destination file does not exist, it is created.
	 * @param in The source file to be copied.
	 * @param out The destination file to write to.
	 */
	public static void copyFile(File in, File out) throws IOException {
	    FileInputStream fis  = new FileInputStream(in);
	    if (!out.exists()) {
	    	if (in.isDirectory()){
	    		out.mkdirs();
	    	} else {
	    		File parentDir = new File(out.getParent());
	    		if (!parentDir.exists()) {
	    			parentDir.mkdirs();
	    		} 
    			out.createNewFile();
	    	}
	    }
	    FileOutputStream fos = new FileOutputStream(out);
	    try {
	        byte[] buf = new byte[ANDROID_BUFFER_8K];
	        int i = 0;
	        while ((i = fis.read(buf)) != -1) {
	            fos.write(buf, 0, i);
	        }
		} catch (IOException e) {
	        throw e;
		} finally {
	        fis.close();
	        fos.close();
	    }
	  }

	/**
	 * copy input stream to output stream
	 * @param in The {@link InputStream} object to be copied from.
	 * @param out The {@link OutputStream} object to write to.
	 * @throws IOException in case copy fails.
	 */
	public static void copyFile(InputStream in, OutputStream out) throws IOException {
		// 8k is the suggest buffer size in android, do not change this
		byte[] buffer = new byte[ANDROID_BUFFER_8K];
		int read;
		while ((read = in.read(buffer)) != -1) {
			out.write(buffer, 0, read);
		}
		out.flush();
	}

	/**
	 * Delete a directory, including all its children.
	 * @param directory The {@link File} object represents the directory to delete. 
	 * @return true if the directory was deleted, false otherwise.
	 */
	public static boolean deleteDirectory(File directory) {
		if(directory.exists()) {
			File[] files = directory.listFiles();
			for(int i=0; i<files.length; i++) {
				if(files[i].isDirectory()) {
					deleteDirectory(files[i]);
				} else {
					files[i].delete();
				}
			}
		}
		return directory.delete();
	}
	
	/**
	 * Convert InputStream data to String
	 * @param is - The InputStream object to be converted
	 * @return The converted string
	 */
	public static String convertStreamToString(InputStream is) {
		BufferedReader reader = new BufferedReader(new InputStreamReader(is));
		StringBuilder sb = new StringBuilder();

		String line = null;
		try {
			while ((line = reader.readLine()) != null) {
				sb.append(line + "\n");
			}
		} catch (IOException e) {
			throw new RuntimeException("Error reding input stream (" + is + ").", e);
		} finally {
			try {
				is.close();
			} catch (IOException e) {
				throw new RuntimeException("Error closing input stream (" + is + ")", e);
			}
		}
		return sb.toString();
	}
	

	public static void debug(String msg){
		Log.d(LOG_CAT, msg);
	}

	public static void error(String msg){
		Log.e(LOG_CAT, msg);
	}	

	public static void warning(String msg){
		Log.w(LOG_CAT, msg);
	}

	public static void info(String msg){
		Log.i(LOG_CAT, msg);
	}

	public static void debug(String msg, Throwable throwable){
		Log.d(LOG_CAT, msg, throwable);
	}

	public static void error(String msg, Throwable throwable){
		Log.e(LOG_CAT, msg, throwable);
	}
	
	public static void log(String msg, int logLevel){
		Log.println(logLevel, LOG_CAT, msg);
	}
	
	public static void writeWLPref(Context context, String prefName, String PrefValue) {
		SharedPreferences prefs = context.getSharedPreferences(WL_PREFS, 0);
		SharedPreferences.Editor editor = prefs.edit();
		editor.putString(prefName, PrefValue);
		editor.commit();
	}
	
	public static String readWLPref(Context context, String prefName) {
		SharedPreferences prefs = context.getSharedPreferences(WL_PREFS, 0);
		return prefs.getString(prefName, null);
	}
}
